package cn.sh.library.mgts.bean;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;

import cn.sh.library.mgts.dto.Pager;
import cn.sh.library.mgts.framework.commonparser.CustomQueryParser;
import cn.sh.library.mgts.framework.commonparser.ParseException;

public class CommonSearchBean {

	//可视化 排序
	private List<String> visualizations = new ArrayList<>();
	
	//检索类型 ： 1-简单；2-高级；3-表达式
	private String searchType = "1";
	
	private String freetext = "";
	
	//检索表达式
	private String expression;
	
	//高级检索条件{"logic"="and/or", "field"="TM", "value"="", "type"="0/1"} 0-模糊，1-精确
	private List<Map<String, String>> cdtn = new ArrayList<Map<String, String>>();
	
	//分面条件{"field"="", "value"=""}
	private Map<String, String> facet = new HashMap<String, String>();
	
	//二次检索条件
	private String secondCdtn;
	
	//分页
	private Pager pager = new Pager();
	
	//排序{"field"="", "type"="0/1"} 1-正，0-倒 
	private Map<String, String> sorts = new HashMap<String,String>();

	//是否分面
	private boolean hasFacet = true;
	
	
	public List<String> getVisualizations() {
		return visualizations;
	}

	public void setVisualizations(List<String> visualizations) {
		this.visualizations = visualizations;
	}

	public String getFreetext() {
		return freetext;
	}

	public void setFreetext(String freetext) {
		this.freetext = freetext;
	}

	public Map<String, String> getSorts() {
		return sorts;
	}

	public void setSorts(Map<String, String> sorts) {
		this.sorts = sorts;
	}

	public boolean isHasFacet() {
		return hasFacet;
	}

	public void setHasFacet(boolean hasFacet) {
		this.hasFacet = hasFacet;
	}

	public String getSearchType() {
		return searchType;
	}

	public void setSearchType(String searchType) {
		this.searchType = searchType;
	}

	public String getExpression() {
		return expression;
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	public List<Map<String, String>> getCdtn() {
		return cdtn;
	}

	public void setCdtn(List<Map<String, String>> cdtn) {
		this.cdtn = cdtn;
	}

	public Map<String, String> getFacet() {
		return facet;
	}

	public void setFacet(Map<String, String> facet) {
		this.facet = facet;
	}

	public String getSecondCdtn() {
		return secondCdtn;
	}

	public void setSecondCdtn(String secondCdtn) {
		this.secondCdtn = secondCdtn;
	}

	public Pager getPager() {
		return pager;
	}

	public void setPager(Pager pager) {
		this.pager = pager;
	}

	public BoolQueryBuilder query(Map<String, String> fieldsMap) throws ParseException {
		BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
		if (this.searchType.equals("1") && StringUtils.isNotBlank(this.freetext)) {
			BoolQueryBuilder q = QueryBuilders.boolQuery();
			List<String> keywords = null;
			keywords = Arrays.asList(this.freetext.trim().split(" "));

			for (String freetext : keywords) {
				for (String field : fieldsMap.get("ALL").split(",")) {
					q.should(QueryBuilders.matchPhraseQuery(field, freetext));
				}
			}
			queryBuilder.must(q);
		} else if (this.searchType.equals("2") && this.cdtn != null
				&& this.cdtn.size() > 0) {
			for (Map<String, String> cdtn : this.cdtn) {
				if(StringUtils.isNotEmpty(cdtn.get("value"))) {
					String logic = StringUtils.isEmpty(cdtn.get("logic")) ? "and"
							: cdtn.get("logic").trim().toLowerCase();
					
					String fields = fieldsMap.getOrDefault(cdtn.get("field"), "undefined");

					BoolQueryBuilder should = QueryBuilders.boolQuery();
					for (String f: fields.split(",")) {
//						String field = f + (cdtn.get("type").equals("1") ? ".keyword" : "");
						should.should(queryCdtn(f, cdtn.get("value").trim(), cdtn.get("type")));
					}

					switch (logic.toLowerCase()) {
					case "and":
						queryBuilder.must(should);
						break;

					case "or":
						queryBuilder.should(should);
						break;

					case "not":
						queryBuilder.mustNot(should);
						break;

					default:
						break;
					}
				}
			}
		} else if(this.searchType.equals("3") && StringUtils.isNotBlank(this.expression)) {
			CustomQueryParser parser = new CustomQueryParser(this.expression, fieldsMap);
			queryBuilder.must(parser.parse());
		}
		
		if(StringUtils.isNotBlank(this.secondCdtn)) {
			BoolQueryBuilder q = QueryBuilders.boolQuery();
			List<String> keywords = null;
			keywords = Arrays.asList(this.secondCdtn.trim().split(" "));

			for (String freetext : keywords) {
				for (String field : fieldsMap.get("ALL").split(",")) {
					q.should(QueryBuilders.matchPhraseQuery(field, freetext));
				}
			}
			queryBuilder.must(q);
		}
		
		return queryBuilder;
	}
	
	QueryBuilder queryCdtn(String field, String value, String type) {// provisionActivity.proDate 1941 1
		QueryBuilder q = QueryBuilders.matchAllQuery();

		switch (type) {
		case "0":
			q = QueryBuilders.matchPhraseQuery(field, value);
			break;

		case "1":
			q = QueryBuilders.matchPhraseQuery(field + ".keyword", value);
			break;

		case "2":
			q = QueryBuilders.rangeQuery(field + ".keyword").from(value);
			break;

		case "3":
			q = QueryBuilders.rangeQuery(field + ".keyword").to(value);
			break;

		case "4":
			q = QueryBuilders.existsQuery(field + ".keyword");
			break;

		case "5":
			q = QueryBuilders.prefixQuery(field, value);

		default:
			q = QueryBuilders.matchPhraseQuery(field, value);
			break;
		}

		return q;
	}
	
	public BoolQueryBuilder facetCdtn(Map<String, String> facetMap) {
		BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
		this.facet.forEach((key, value) -> {
			String fieldname = facetMap.getOrDefault(key, key);
			if(StringUtils.isNotBlank(value)) {
				for (String v : value.split(" ")) {
					queryBuilder.must(QueryBuilders.matchPhraseQuery(fieldname + ".keyword", v));
				}
			}
		});
		return queryBuilder;
	}

	public List<SortBuilder<?>> sortSB(Map<String, String> sortMap){
		List<SortBuilder<?>> list = new ArrayList<SortBuilder<?>>();
		sorts.forEach((key, value) -> {
			SortOrder sortOrder = SortOrder.ASC;
			if("0".equals(value)) {
				sortOrder = SortOrder.DESC;
			}
				//根据字段排序
			String sortField = sortMap.get(key);
			if(!StringUtils.isEmpty(sortField)) {
				list.add(SortBuilders.fieldSort(sortField).order(sortOrder));
			}
		});
		
		return list;
	}
	
	
	public static void main(String[] args) {
		String exp = "ty=\"P,D\" and DT=\"JP\" and tm=ssss AND zrz=PAUL";
		exp = "ty=P,D and DT=JP and tm=ssss AND zrz=PAUL";
		CustomQueryParser parser = new CustomQueryParser(exp);
		try {
			System.out.println(parser.parse());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.println(parser.getTypes());
		System.out.println(parser.getDocTypes());
		
	}
}
